<?php

namespace Service\CommodityService;

use Service\BaseService;
use Service\InterfaceService\WebSocketInterface;
use Service\Code\Normal;
use App\Model\CommodityModel\Stockinfo;
use App\Model\CommodityModel\CommodityOptimizationBbc;
use App\Model\PssModel\Sysconfig;
use App\Model\CommodityModel\CommodityChannelBestGoods;
use App\Model\CommodityModel\SupplierCommodityTag;
use App\Model\PssModel\Business;
use Service\AppService\IdService;
use Service\AuthService\ManageWsUserAuthService;
use Hyperf\Utils\WaitGroup;
use Hyperf\Task\Annotation\Task;
use Hyperf\DbConnection\Db;
use App\Model\CommodityModel\StockInfoUser;

class CommodityOptimizationService extends BaseService implements WebSocketInterface
{
    const GOODS_SETTING_MODE_BASE       = 1;//基础配置
    const GOODS_SETTING_MODE_ADVANCE    = 2;//高级配置
    const SUPPLIER_CHOICE_MODE_WH       = 1;//指定供应商
    const SUPPLIER_CHOICE_MODE_SP       = 2;//指定商品
    const PAGE_LIMIT                    = 2000;
    const PAGE_UNIQUE_SKU_LIMIT         = 200;
    
    //是否指定商品导入
    protected $IsImportGoods        = false;
    //是否有库存范围限制
    protected $IsStockNumberLimit   = false;
    //是否有校期限制
    protected $IsGoodsExpireLimit   = false;
    
    /**
     * 接收websocket消息
     */
    public function onMessage($server,$frame)
    {
        $paramters      = @json_decode($frame->data,true);
        $res            = $this->checkLogin($paramters);
        if( $res['code'] != Normal::SUC ) {
            $send = Normal::returnCode(Normal::WS_ERROR,$res['msg']);
            return $server->push($frame->fd,json_encode($send,JSON_UNESCAPED_UNICODE));
        }
        
        $systemUser     = $res['data'];
        $receive_data   = $paramters['requestData'];
        $bid            = $receive_data['bid'];

        //检查请求参数
        $resQueryParam  = $this->getWhereParameters($receive_data);
        if( $resQueryParam['code'] != Normal::SUC ) {
            $send = Normal::returnCode(Normal::WS_ERROR,$resQueryParam['msg']);
            return $server->push($frame->fd,json_encode($send,JSON_UNESCAPED_UNICODE));
        }
        
        //开始处理查询规则
        $where          = $resQueryParam['data'];
        
        //是否立即保存并且授权
        if( isset($receive_data['AuthGoodsType']) && $receive_data['AuthGoodsType'] == 1 ) 
        {
            //渠道商户
            if( $bid > 0 ) 
            {
                $businfo = Business::instance()->info(['id'=>$bid]);
                //是否初次授权
                if( $businfo['has_template'] != 1) {
                    $send = Normal::returnCode(Normal::WS_ERROR,'当前商户初次授权商品，不允许直接操作保存并且授权，需要进入下一步进行价格模板设置！');
                    return $server->push($frame->fd,json_encode($send,JSON_UNESCAPED_UNICODE));
                }
            
                //是否正在授权商品中
                if( $businfo['sync_status'] == 2 ) {
                    $send = Normal::returnCode(Normal::WS_ERROR,'当前商户正在同步授权商品，请耐心等候！');
                    return $server->push($frame->fd,json_encode($send,JSON_UNESCAPED_UNICODE));
                }
            } else {
                //商城模板
                $info = Sysconfig::instance()->getShopTemplate();
                if( empty($info) || empty($info['contents']) ) {
                    $send = Normal::returnCode(Normal::WS_ERROR,'当前商户初次授权商品，不允许直接操作保存并且授权，需要进入下一步进行价格模板设置！');
                    return $server->push($frame->fd,json_encode($send,JSON_UNESCAPED_UNICODE));
                }
                
                //正在授权
                if( $info['value'] == 1 ) {
                    $send = Normal::returnCode(Normal::WS_ERROR,'当前商户正在同步授权商品，请耐心等候！');
                    return $server->push($frame->fd,json_encode($send,JSON_UNESCAPED_UNICODE));
                }
            }
        }
        
        //对接请求参数规则
        $receive_data['sys_user_id'] = $systemUser['id'];
        $clientInfo     = $server->getClientInfo($frame->fd);
        $json = json_encode($receive_data,JSON_UNESCAPED_UNICODE);
        $log = ["content"=>"操作优选规则【{$json}】","ip"=>$clientInfo['remote_ip']??'0.0.0.0','sys_user_id'=>$systemUser['id'],'sys_user_name'=>$systemUser['name']];
        ManageWsUserAuthService::instance()->addSystemLog($log);
        
        //渠道商户
        $is_router_user = 0;
        $is_channel  = 0;
        $is_full_support_after_sale = 0;
        if( $bid > 0 )
        {
            $businfo = Business::instance()->getUserInfoByBid($bid);
            $is_channel = $businfo['is_channel'];
            $is_full_support_after_sale = $businfo['is_full_support_after_sale'];
            if( $businfo['sync_mode'] == 1 ) {
                $send = Normal::returnCode(Normal::WS_ERROR,'请勿重复点击，当前优选规正在处理中');
                Business::instance()->where('id',$bid)->update(['sync_mode'=>0]);
                return $server->push($frame->fd,json_encode($send,JSON_UNESCAPED_UNICODE));
            }
        
            $is_router_user = $businfo['is_router_user'];
            //下游bbc渠道保持资料完整
            if( $businfo['is_router_user'] != 1 ) {
                $where['baseWhere'][] = "com.IsIntegrity =1";
            }
            Business::instance()->where('id',$bid)->update(['sync_mode'=>1]);
        } else {
            //商城模板保持资料完整
            $where['baseWhere'][] = "com.IsIntegrity =1";
        
            //商城模板
            $info = Sysconfig::instance()->getShopTemplate();
            if( $info['small_type'] == 1 ) {
                $send = Normal::returnCode(Normal::WS_ERROR,'请勿重复点击，当前优选规正在处理中');
                Sysconfig::instance()->where('id',$info['id'])->update(['small_type'=>0]);
                return $server->push($frame->fd,json_encode($send,JSON_UNESCAPED_UNICODE));
            }
        
            Sysconfig::instance()->where('id',$info['id'])->update(['small_type'=>1]);
        }
        
        
        $percent = 0;
        //获取数据总条数
        $totalCount     = $this->getBestGoodsCountBySubQuery($bid,$where,$receive_data,$is_channel,$is_full_support_after_sale);
        if( $totalCount <= 0 ) {
            $send = Normal::returnCode(Normal::WS_ERROR,"当前优选授权规则条件下,未找到满足条件的数据，请核对优选规则是否正确！");
            return $server->push($frame->fd,json_encode($send,JSON_UNESCAPED_UNICODE));
        }
        
        //开始分页写入数据
        $pageCount = ceil($totalCount/self::PAGE_LIMIT);
        
        //重置IsInit
        CommodityOptimizationBbc::instance()->getTableByBuID($bid)->where('BuID',$bid)->update([
            'IsInit' => 0,
        ]);
        
        for($page = 1 ; $page <= $pageCount ; $page++)
        {
            $dataList = $this->getBestGoodsPageList($bid,$where,$receive_data,$page,self::PAGE_LIMIT,$is_channel,$is_full_support_after_sale);

            if( !empty($dataList) ) 
            {
                foreach ($dataList as $key => & $value)
                {
                    //如果当前锁仓库存大于0，则当前渠道用户对应商品批次数据，肯定是有数据
                    if( $value['StockRemainNumber'] <= 0 && $value['Number'] <= 0 && $value['NumberLock'] > 0 ) {
                        unset($dataList[$key]);
                        continue;
                    }
                    
                    $value['ID']            = IdService::instance()->getOtherID();
                    $value['BuID']          = $receive_data['bid'];
                    $value['IsInit']        = 1;
                    $SaleFirstSupplierlist  = $receive_data['GoodsAdvanceSettings']['SaleFirstSupplierlist'] ?? [] ;
                    $value['IsSaleFirst']   = !empty($SaleFirstSupplierlist) && in_array($value['SupplierCompanyID'], $SaleFirstSupplierlist) ? 1 : 0 ;
                    $value['CreateTime']    = date("Y-m-d H:i:s");
                    $value['CommodityStatus'] = 1;
                    
                    if( isset($value['SupplierCompanyID']) ) {unset($value['SupplierCompanyID']);}
                    if( isset($value['StockRemainNumber']) ) {unset($value['StockRemainNumber']);}
                    if( isset($value['Number']) ) {unset($value['Number']);}
                    if( isset($value['NumberLock']) ) {unset($value['NumberLock']);}
                }
                
                if( empty($dataList) ) {
                    continue;
                }
                
                //开始处理数据库
                $res = $this->CommodityOptimizationWrite($bid,$dataList);
                if( $res['code'] != Normal::WS_START ) {
                    return $server->push($frame->fd,json_encode($res,JSON_UNESCAPED_UNICODE));
                }
            }
            
            if ( $page == $pageCount ) 
            {
                $percent    = $is_router_user == 1 ? '100.00' : '50.00';//最后一页数据处理
            } 
            else 
            {
                $times      = $is_router_user == 1 ? 1 : 2;
                $percent    = bcdiv($page,$pageCount* $times,4);
                $percent    = bcmul($percent,100, 2);
            }
            
            $send = Normal::returnCode(Normal::WS_START, "进行中", [
                'percent' => $percent
            ]);
            $server->push($frame->fd,json_encode($send,JSON_UNESCAPED_UNICODE));
        }
        
        //如果不是路由模式用户就不用处理一对一关系
        if( $is_router_user != 1 )
        {
            $totalSkuCount = $this->getUserCommodityOneRelationCount($bid);
            if( $totalSkuCount > 0 )
            {
                $eventID = IdService::instance()->getOtherID();
                
                //开始写数据到一对一关系商品表
                $pageSkuCount = ceil($totalSkuCount/self::PAGE_UNIQUE_SKU_LIMIT);
                for($pageIndex = 1; $pageIndex <= $pageSkuCount; $pageIndex ++)
                {
                    $dataList = $this->getUserCommodityOneRelationDataList($bid,$pageIndex,self::PAGE_UNIQUE_SKU_LIMIT);
                    $sku_ids = array_column($dataList,'SkuID');
                    if( $sku_ids )
                    {
                        //需要将一对一关系商品表全部下架
                        $bestGoods = $this->getChannelBestGoodsDataList($bid,$sku_ids);
                        
                        //获取优先售卖的数据
                        $bestSaleFirstGoods = $this->getChannelBestGoodsDataList($bid,$sku_ids,['IsSaleFirst'=>1]);
                        $bestSaleFirstGoodsMap = array_column($bestSaleFirstGoods,null,'SkuID');
                        
                        //优选售卖商品的逻辑
                        foreach ($bestGoods as & $item) 
                        {
                            if( isset($bestSaleFirstGoodsMap[$item['SkuID']]) ) 
                            {
                                $item = $bestSaleFirstGoodsMap[$item['SkuID']];
                            }
                        }
                        
                        //获取最新的stockInfoID
                        $stockInfoIDs = array_column($bestGoods,'StockInfoID');
                        
                        //是否有锁仓库存
                        $stockUserMap = StockInfoUser::instance()->getStockUserByBidsAndIds($bid,$stockInfoIDs);
                        foreach ($bestGoods as & $item) 
                        {
                            if (isset($stockUserMap[$item['StockInfoID']]))
                            {
                                $item['Number']=$stockUserMap[$item['StockInfoID']]['StockRemainNumber'];
                            }                            
                        }
                        
                        //开始写入数据
                        $this->CommodityBestGoodsWrite($bid,$eventID,$bestGoods);
                    }
                    
                    if ( $pageIndex == $totalSkuCount ) 
                    {
                        $commodity_channel_percent = '49.99';//最后一页数据处理
                    }
                    else
                    {
                        $commodity_channel_percent = bcdiv($pageIndex, $pageSkuCount * 2, 4);
                        $commodity_channel_percent = bcmul($commodity_channel_percent, 100, 2);
                    }
                    
                    $send = Normal::returnCode(Normal::WS_START, "进行中", [
                        'percent' => bcadd($commodity_channel_percent, $percent,2)
                    ]);                    
                    $server->push($frame->fd,json_encode($send,JSON_UNESCAPED_UNICODE));
                }
                
                //需要将非当前初始化数据全部下架
                CommodityChannelBestGoods::instance()->getTableByBuID($bid)->where('BuID',$bid)->where('SelfBuild',0)->where('eventID','<>',$eventID)->update([
                    'CommodityStatus'   => 0
                ]);
            }
            else
            {
                //需要将一对一关系商品表全部下架
                CommodityChannelBestGoods::instance()->getTableByBuID($bid)->where('BuID',$bid)->where('SelfBuild',0)->update([
                    'CommodityStatus'   => 0
                ]);
            }
        }
        
        //写入优选商品池数据完成之后，更新当前渠道优选规则
        $template = json_encode($receive_data,JSON_UNESCAPED_UNICODE);
        if( $bid > 0 ) {
            $updateBus = [
                'template'              => $template,
                'has_template'          => 1,
                'template_update_time'  => time(),
                'is_goods_expire'       => $this->IsGoodsExpireLimit ? 1 : 0,
                'is_stock_limit'        => $this->IsStockNumberLimit ? 1 : 0,
                'is_import_goods'       => $this->IsImportGoods ? 1 : 0,
                'sync_mode'             => 0,
            ];
            
            //保存立即授权
            if( isset($receive_data['AuthGoodsType']) && $receive_data['AuthGoodsType'] == 1 ) {
                $updateBus['is_sync']   = 1;
                $updateBus['sync_type'] = 1;
                $updateBus['sync_status'] = 0;
            }
            
            $this->IsImportGoods = false;
            $this->IsGoodsExpireLimit = false;
            $this->IsStockNumberLimit = false;
            
            //更新优选规则
            Business::instance()->where('id',$bid)->update($updateBus);
        } else {
            //保存立即授权
            $is_sync = false;
            if( isset($receive_data['AuthGoodsType']) && $receive_data['AuthGoodsType'] == 1 ) {
                $is_sync = true;
            }
            Sysconfig::instance()->updateContents($template,$is_sync);
        }
        
        //处理结束
        $send = Normal::returnCode(Normal::WS_END, "处理结束", [
            'percent' => "100.00"
        ]);
        $server->push($frame->fd,json_encode($send,JSON_UNESCAPED_UNICODE));
    }
    
    /**
     * 获取优选商品一对一关系数据商品总数
     * 兼容渠道和云仓商城
     * @param int $BuID
     */
    public function getUserCommodityOneRelationCount(int $BuID)
    {
        $row = CommodityOptimizationBbc::instance()->getTableByBuID($BuID)
        ->select([
            Db::raw("count(DISTINCT SkuID) AS total")
        ])
        ->where('BuID',$BuID)
        ->where('CommodityStatus',1)
        ->where('IsInit',1)
        ->first()
        ->toArray();
        return (int)$row['total'];
    }
    
    /**
     * 获取优选商品一对一关系数据商品明细
     * 兼容渠道和云仓商城
     * @param int $BuID
     */
    public function getUserCommodityOneRelationDataList(int $BuID,int $page,int $limit = 100)
    {
        $pageOffset = ($page-1) * $limit;
        return CommodityOptimizationBbc::instance()->getTableByBuID($BuID)
        ->select([
            Db::raw("DISTINCT SkuID as SkuID")
        ])
        ->where('BuID',$BuID)
        ->where('CommodityStatus',1)
        ->where('IsInit',1)
        ->orderBy('SkuID','asc')
        ->offset($pageOffset)
        ->limit($limit)
        ->get()
        ->toArray();
    }
    
    /**
     * 获取指定商品sku_ids 最优解数据
     * @param int $bid
     * @param array $u_sku_ids
     * @param array $extra
     */
    public function getChannelBestGoodsDataList( int $bid = 0,array $u_sku_ids,array $extra = [])
    {
        $table = CommodityOptimizationBbc::instance()->getTableByBuID($bid)->getTable();
        
        //第一次拿出最低价格的数据
        $minPriceSubQuery = CommodityOptimizationBbc::instance()->getTableByBuID($bid)
        ->from($table . " as a_cop")
        ->select([
            'a_cop.SkuID',
            Db::raw('min(a_cop.BatchSpecMinSinglePrice) AS BatchSpecMinSinglePrice')
        ])
        ->where('a_cop.BuID',$bid)
        ->whereIn('a_cop.SkuID',$u_sku_ids);
        
        //是否优先售卖商品
        if( isset($extra['IsSaleFirst']) && $extra['IsSaleFirst'] == 1 ) {
            $minPriceSubQuery->where('a_cop.IsSaleFirst',1);
        }        
        
        $minPriceSubQuery->where('a_cop.CommodityStatus',1)
        ->where('a_cop.IsInit',1)
        ->groupBy("a_cop.SkuID");
    
        //第二次再按照最低价格的数据分组，再对skuid 分组取每一组里面行数据ID 最大的ID,防止出现相同价格数据，导致授权主档案资料数据重复
        $secondSubQuery = CommodityOptimizationBbc::instance()->getTableByBuID($bid)
        ->from($table." AS b")
        ->select([
            Db::raw("max(b.ID) AS max_id")
        ])
        ->joinSub($minPriceSubQuery,"a",function($join)
        {
            $join->on('a.SkuID', '=', 'b.SkuID')->on('a.BatchSpecMinSinglePrice','=','b.BatchSpecMinSinglePrice');
        })
        ->groupBy("b.SkuID")
        ->where('b.BuID',$bid)
        ->where('b.CommodityStatus',1);
        
        //是否优先售卖商品
        if( isset($extra['IsSaleFirst']) && $extra['IsSaleFirst'] == 1 ) {
            $secondSubQuery->where('b.IsSaleFirst',1);
        }
        
        //第三次查询，根据拿出来优选池里面最小ID数据进行，匹配满足授权数据
        $table = CommodityOptimizationBbc::instance()->getTableByBuID($bid)->getTable();
        return CommodityOptimizationBbc::instance()->getTableByBuID($bid)
        ->from($table." AS cop")
        ->select($this->getBestGoodsColumns())
        ->joinSub($secondSubQuery,"sec_b",function($join)
        {
            $join->on('sec_b.max_id', '=', 'cop.ID');
        })
        ->join("stockinfo_s2b as stock","stock.ID","=","cop.StockInfoID")
        ->join("commodityarchives_s2b as com","com.ID","=","stock.CommodityArchivesID")
        ->join("commoditydescription_s2b as cds",function($join)
        {
            $join->on("cds.CommodityInfoID","=","com.ID")
            ->where("cds.IsDeleted",0);
        })
        ->leftJoin("spuattr_s2b as spu","spu.ID","=","com.SpuID")
        ->join("suppliercommodity_s2b as scb","scb.ID","=","cop.SupplierSKUID")
        ->leftJoin("suppliercommoditycustominfo_s2b as scb_cus",function($join)
        {
            $join->on("scb_cus.SupplierCommodityID","=","cop.SupplierSKUID")
            ->where("scb_cus.IsDeleted",0);
        })
        ->join("classifyinfo_s2b as f_class","f_class.ID","=","com.FirstClassificationID")
        ->join("classifyinfo_s2b as s_class","s_class.ID","=","com.SecondClassificationID")
        ->join("classifyinfo_s2b as t_class","t_class.ID","=","com.ThirdClassificationID")
        ->join("brandinfo_s2b as b","b.ID","=","com.BrandID")
        ->join("countryinfo_s2b as c","c.ID","=","com.CountryID")
        ->leftJoin("unitinfo_s2b as u","u.ID","=","com.UnitID")
        ->join("warehouseinfo_s2b as w","w.ID","=","stock.WarehouseID")
        ->join("suppliercompany_s2b as s","s.ID","=","stock.SupplierCompanyID")
        ->where("com.SelfBuild",0)
        ->get()
        ->toArray();
    }
    
    /**
     * 增量更新优选池数据
     * @Task
     * @param array $receive_data
     */
    public function getUserSkuIDChange( $param = [] )
    {
        if( empty($param['bids']) ) {
            return Normal::returnCode(Normal::FAIL,"用户bids组不能为空");
        }
        
        if( empty($param['SkuIDS']) && empty($param['SupplierSKUIDS'])) {
            return Normal::returnCode(Normal::FAIL,"商品数据SkuIDS或者供应商商品SupplierSKUIDS不能为空");
        }
        
        $bids = $param['bids'];
        $bids = array_unique($bids);
        if( empty($bids) ) {
            return Normal::returnCode(Normal::FAIL,"用户IDs组不能为空");
        }
        
        //商城模板
        if( in_array('0', $bids) && count($bids) == 1 ) {
            $shopTemplate = Sysconfig::instance()->getShopTemplate();
            $content = json_decode($shopTemplate['contents'],true);
            $content['id'] = $content['bid'];
            $busList =  [$content]; 
        } else {
            $busList = Business::instance()->getUserInfoTemplatesByBids($bids);
        }
        
        $result = [];
        $count = count($busList);
        $wg = new \Hyperf\Utils\WaitGroup();
        $wg->add($count);
        foreach ($busList as $binfo )
        {
            co(function () use ($wg,$binfo,$param,& $result ) 
            {
                $receive_data   = @json_decode($binfo['template'],true);
                $extra = [];
                if( !empty($param['SkuIDS']) ) {
                    $receive_data['SkuIDS'] = $param['SkuIDS'];
                    $extra = [
                        'SkuIDS'    => $param['SkuIDS'],
                    ];
                }
        
                if( !empty($param['SupplierSKUIDS']) ) {
                    $receive_data['SupplierSKUIDS'] = $param['SupplierSKUIDS'];
                    $extra = [
                        'SupplierCommodityIDs'    => $param['SupplierSKUIDS'],
                    ];
                }
                
                $bid = $binfo['id'];
                
                //组装请求数据
                $resQueryParam  = $this->getWhereParameters($receive_data);
                if( $resQueryParam['code'] != Normal::SUC ) 
                {
                    $result[$bid] = $resQueryParam;
                } 
                else 
                {
                    $where = $resQueryParam['data'];
                    
                    //商城模板或者下游bbc渠道保持资料完整
                    if( $bid == 0 || (isset($binfo['is_router_user']) && $binfo['is_router_user'] != 1) ) {
                        $where['baseWhere'][] = "com.IsIntegrity=1";
                    }
                    
                    
                    $extra['is_channel'] = isset($binfo['is_channel']) && $binfo['is_channel'] == 1 ? 1 : 0;
                    $extra['is_full_support_after_sale'] = isset($binfo['is_full_support_after_sale']) && $binfo['is_full_support_after_sale'] == 1 ? 1 : 0;
                    
                    //获取子查询   TODO           
                    if( !empty($extra['SkuIDS']) ) {
                        $firstSubQuery = $this->getFirstSubQuery($bid, $where, $receive_data,4,$extra);
                    } else {
                        $firstSubQuery = $this->getFirstSubQuery($bid, $where, $receive_data,3,$extra);
                    }

                    //第二次子查询
                    $secondSubQuery = $this->getSecondSubQuery($firstSubQuery,$where);
                    //第三次子查询 取出优选数据
                    $goodsList = $this->getThirdSubQuery($secondSubQuery,$bid,$extra['is_channel'],$extra['is_full_support_after_sale']);
                    $result[$bid]['goodsList']  = $goodsList;
                    $result[$bid]['binfo']      = $binfo;
                }
                $wg->done();
            });
        }
        $wg->wait();
        return Normal::returnCode(Normal::SUC,"处理成功",$result);        
    }
    
    /**
     * 处理优选表数据
     * @return mixed
     */
    public function CommodityOptimizationWrite($bid, $dataList = [] )
    {
        $supplierSkuIDList = array_column($dataList,null,'SupplierSKUID');
        $columns = ['ID','SupplierSKUID'];
        $hasList = CommodityOptimizationBbc::instance()->getTableByBuID($bid)->where('BuID',$bid)->whereIn('SupplierSKUID',array_keys($supplierSkuIDList))->get()->toArray();
        try {
        
            CommodityOptimizationBbc::instance()->getTableByBuID($bid)->startTrans();
            
            //如果存在需要更新的数据
            if( $hasList ) {
                
                //需要更新的字段
                $updateSqlColumns = [
                    'SkuID',
                    'SKUCode',
                    'SupplierSKUCode',
                    'BatchNo',
                    'StockInfoID',
                    'BatchSpecMinSinglePrice',
                    'SpecList',
                    'IsInit',
                    'IsSaleFirst',
                    'UpdateTime',
                    'PriceRuleType',
                    'IsPriceSet',
                    'CommodityStatus'
                ];
                
                foreach ($hasList as $key => $item ) 
                {
                    //防止重复的数据
                    if( ! isset($supplierSkuIDList[$item['SupplierSKUID']]) ) 
                    {
                        //需删除当前重复的那一条数据
                        CommodityOptimizationBbc::instance()->getTableByBuID($bid)->where('ID',$item['ID'])->delete();
                        unset($hasList[$key]);
                        continue;
                    }
                    
                    //如果存在数据并且和当前优选商品SKU一直则更新
                    $postData = $supplierSkuIDList[$item['SupplierSKUID']];
                    foreach ($updateSqlColumns as $column)
                    {
                        if( $column == 'UpdateTime' ) {
                            $then  = date("Y-m-d H:i:s");
                        }else if( $column == 'SupplierSKUCode' ) {
                            $then  = addslashes($postData[$column]);
                        } else if( in_array($column, ['IsPriceSet','PriceRuleType']) ) {
                            $then = '0';
                        } else {
                            $then  = $postData[$column];
                        }
                        ${$column}[] = "WHEN {$item['ID']} THEN '{$then}'";
                    }
                    unset($supplierSkuIDList[$item['SupplierSKUID']]);
                }
                
                //如果有存在更新的数据
                if( $hasList ) {
                    $whenSql = [];
                    foreach ($updateSqlColumns as $column)
                    {
                        $whenSql[] = "{$column} = CASE ID " .(implode(" ", ${$column})) . " END";
                    }
                    $whenBatchUpdateSql = implode(",", $whenSql);
                    $whereIds = implode(",", array_column($hasList,'ID'));
                    
                    //批量更新数据
                    $connectName    = CommodityOptimizationBbc::instance()->getConnectionName();
                    $databaseName   = CommodityOptimizationBbc::instance()->getTableByBuID($bid)->getConnection()->getDatabaseName();
                    $tableName      = CommodityOptimizationBbc::instance()->getTableByBuID($bid)->getTable();
                    $sql_batch_sql  = "UPDATE `{$databaseName}`.`{$tableName}` SET {$whenBatchUpdateSql} WHERE ID IN({$whereIds})";
                    Db::connection($connectName)->update($sql_batch_sql);
                }
            }
            
            //如果存在新增的数据
            if( $supplierSkuIDList ) {
                CommodityOptimizationBbc::instance()->getTableByBuID($bid)->insert($supplierSkuIDList);
            }
            
            CommodityOptimizationBbc::instance()->getTableByBuID($bid)->commit();
            return Normal::returnCode(Normal::WS_START,"处理成功");
        } catch ( \Throwable $th ) {
            CommodityOptimizationBbc::instance()->getTableByBuID($bid)->rollback();
            return Normal::returnCode(Normal::WS_ERROR,$th->getMessage(),[
                'errorFile' => $th->getFile(),
                'errorLine' => $th->getLine()    
            ]);
        }
    }
    
    /**
     * 处理最优商品数据写入
     * @param int $bid
     * @param bigint $eventID
     * @param array $dataList
     * @return unknown[]|string[]|array[]
     */
    public function CommodityBestGoodsWrite(int $bid,int $eventID,array $dataList)
    {
        try {
            $bestGoodsMapList = array_column($dataList, null,'SkuID');
            $sku_ids = array_keys($bestGoodsMapList);
            //批量操作
            $hasDataList = CommodityChannelBestGoods::instance()->getTableByBuID($bid)->where('BuID',$bid)->whereIn('SkuID',$sku_ids)->get()->toArray();
            $updateDataList = [];
            foreach ($hasDataList as $item) {
                $SkuID = $item['SkuID'];
                $updateDataList[$SkuID] = $bestGoodsMapList[$SkuID];
                unset($bestGoodsMapList[$SkuID]);
            }
            
            CommodityChannelBestGoods::instance()->getTableByBuID($bid)->startTrans();
            
            //批量写入
            if( !empty($bestGoodsMapList) )
            {
                $insertAllGoodsList = [];
                foreach ($bestGoodsMapList as $item)
                {
                    $insertAllGoodsList[] =
                    [
                        'ID'                        => IdService::instance()->getOtherID(),
                        'BuID'                      => $bid,
                        'SkuID'                     => $item['SkuID'],
                        'SupplierSKUID'             => $item['SupplierSKUID'],
                        'StockInfoID'               => $item['StockInfoID'],
                        'SpecList'                  => $item['SpecList'],
                        'Number'                    => $item['Number'],
                        'CommodityStatus'           => 1,
                        'CommodityOptimizationID'   => $item['CopID'],
                        'EventID'                   => $eventID,
                        'CreateTime'                => date("Y-m-d H:i:s")
                    ];
                }
                CommodityChannelBestGoods::instance()->getTableByBuID($bid)->insert($insertAllGoodsList);
            }
            
            
            //如果存在需要更新的数据
            if( $hasDataList )
            {
                //需要更新的字段
                $updateSqlColumns = [
                    'SupplierSKUID',
                    'StockInfoID',
                    'Number',
                    'SpecList',
                    'CommodityStatus',
                    'CommodityOptimizationID',
                    'EventID',
                    'UpdateTime'
                ];
                
                foreach ($hasDataList as $item ) 
                {
                    //如果存在数据并且和当前优选商品SKU一直则更新
                    $postData = $updateDataList[$item['SkuID']];
                    foreach ($updateSqlColumns as $column)
                    {
                        if( $column == 'UpdateTime' ) {
                            $then  = date("Y-m-d H:i:s");
                        } else if( $column == 'CommodityStatus' ) {
                            $then  = 1;
                        } else if( $column == 'EventID' ) {
                            $then  = $eventID;
                        } else {
                            $then  = $postData[$column];
                        }
                        ${$column}[] = "WHEN {$item['ID']} THEN '{$then}'";
                    }
                    unset($updateDataList[$item['SkuID']]);
                }
                
                //如果有存在更新的数据
                if( $hasDataList ) 
                {
                    $whenSql = [];
                    foreach ($updateSqlColumns as $column)
                    {
                        $whenSql[] = "{$column} = CASE ID " .(implode(" ", ${$column})) . " END";
                    }
                    $whenBatchUpdateSql = implode(",", $whenSql);
                    $whereIds = implode(",", array_column($hasDataList,'ID'));
                    
                    //批量更新数据
                    $connectName = CommodityChannelBestGoods::instance()->getConnectionName();
                    $databaseName   = CommodityChannelBestGoods::instance()->getTableByBuID($bid)->getConnection()->getDatabaseName();
                    $tableName      = CommodityChannelBestGoods::instance()->getTableByBuID($bid)->getTable();
                    $sql_batch_sql  = "UPDATE `{$databaseName}`.`{$tableName}` SET {$whenBatchUpdateSql} WHERE ID IN({$whereIds})";
                    Db::connection($connectName)->update($sql_batch_sql);
                }
            }
            CommodityChannelBestGoods::instance()->getTableByBuID($bid)->commit();
            return Normal::returnCode(Normal::WS_START,"处理成功");
        } catch ( \Throwable $th ) {
            CommodityChannelBestGoods::instance()->getTableByBuID($bid)->rollback();
            return Normal::returnCode(Normal::WS_ERROR,$th->getMessage(),[
                'errorFile' => $th->getFile(),
                'errorLine' => $th->getLine()    
            ]);
        }
    }
    
    /**
     * 获取优选池字段
     * @return mixed
     */
    public function getGoodsColumns()
    {
        return [
            Db::raw("outter_com.ID AS SkuID"),
            Db::raw("outter_com.SKUCode"),
            Db::raw("outter_scb.SupplierCommoditySkuCode AS SupplierSKUCode"),
            Db::raw("CONCAT(outter_scb.ID,'') AS SupplierSKUID"),
            Db::raw("CONCAT(outter_stb.ID,'') AS StockInfoID"),
            Db::raw("outter_stb.BatchNo"),
            Db::raw("CONCAT(outter_stb.SupplierCompanyID,'') as SupplierCompanyID"),
            "outter_stb.BatchSpecMinSinglePrice",
            "outter_stb.SpecList",
            Db::raw("outter_stb.Number"),
            Db::raw("outter_stb.NumberLock"),
            Db::raw("IFNULL(u_stock.StockRemainNumber,0) AS StockRemainNumber"),
        ];
    }
    
    /**
     * 获取优选池里面最优商品属性字段
     * @return mixed
     */
    public function getBestGoodsColumns()
    {
        return [
            Db::raw("cop.ID AS CopID"),
            Db::raw("cop.SkuID"),
            Db::raw("cop.SupplierSKUID"),
            Db::raw("cop.StockInfoID"),
            Db::raw("cop.SpecList"),
            Db::raw("cop.ID AS CommodityOptimizationID"),
            Db::raw("stock.Number")
        ];
    }
    
    /**
     * 获取增量更新字段
     * @return mixed
     */
    public function getNotifyChangeGoodsColumns()
    {
        return [
            Db::raw("CONCAT(outter_com.ID,'') AS SkuID"),
            Db::raw("CONCAT(outter_com.SKUCode,'') AS SKUCode"),
            Db::raw("CONCAT(outter_scb.SupplierCommoditySkuCode,'') AS SupplierSKUCode"),
            Db::raw("CONCAT(outter_scb.ID,'') AS SupplierSKUID"),
            Db::raw("CONCAT(outter_stb.ID,'') AS StockInfoID"),
            Db::raw("CONCAT(outter_stb.SupplierCompanyID,'') AS SupplierCompanyID"),
            Db::raw("CONCAT(outter_stb.BatchID,'') AS BatchID"),
            Db::raw("IFNULL(outter_stb.LimitBuyCount,0) AS LimitBuyCount"),
            Db::raw("IFNULL(outter_stb.Number,0) AS Number"),
            "outter_stb.BatchNo",
            "outter_stb.SpecList",
            Db::raw("IFNULL(outter_stb.CalibrationPeriodTime,'') AS CalibrationPeriodTime"),
            "outter_stb.BatchSpecMinSinglePrice",
            Db::raw("IFNULL(outter_stb.IsDefective,0) AS IsDefective"),
            Db::raw("outter_stb.Number"),
            Db::raw("outter_stb.NumberLock"),
            Db::raw("IFNULL(u_stock.StockRemainNumber,0) AS StockRemainNumber"),
        ];
    }
    
    /**
     * 获取满足优选条件总商品数量
     * @param int $bid
     * @param array $where
     * @param array $receive_data
     * @param int $is_channel
     * @param int $is_full_support_after_sale
     */
    public function getBestGoodsCountBySubQuery(int $bid,array $where,$receive_data,int $is_channel,int $is_full_support_after_sale)
    {
        $result = $this->getFirstSubQuery($bid,$where,$receive_data,1,['is_channel'=>$is_channel,'is_full_support_after_sale'=>$is_full_support_after_sale]);
        return $result['total'];
    }
    
    /**
     * 查询优选分页参数
     * @param int $bid
     * @param array $where
     * @param array $receive_data
     * @param int $page
     * @param int $limit
     * @param int $is_channel
     * @param int $is_full_support_after_sale
     */
    public function getBestGoodsPageList(int $bid,array $where,array $receive_data,int $page,int $limit,int $is_channel,int $is_full_support_after_sale)
    {
        //查询指定分组分页数据
        $extra = [
            'page'          => $page,
            'limit'         => $limit,
            'is_channel'    => $is_channel,
            'is_full_support_after_sale'    => $is_full_support_after_sale,
        ];
        
        
        $subQuery = $this->getFirstSubQuery($bid,$where,$receive_data,2,$extra);
        $dataList = $subQuery->get()->toArray();
        

        if( empty($dataList) ) {
            return [];
        }
        
        //分页要使用最新的逻辑来使用,这里将最后一个ID存入
        //查询每组数据里面，满足条件的供应商商品
        $supplierCommodityIDs = array_column($dataList,'SupplierCommodityID');
        $extra = [
            'SupplierCommodityIDs'  =>  $supplierCommodityIDs
        ];
        
        //第一次子查询
        $firstSubQuery = $this->getFirstSubQuery($bid,$where,$receive_data,3,$extra);
        //第二次子查询
        $secondSubQuery = $this->getSecondSubQuery($firstSubQuery,$where);
        //第三次子查询 取出优选数据
        return $this->getThirdSubQuery($secondSubQuery,$bid,$is_channel,$is_full_support_after_sale);
    }
    
    /**
     * 获取第三次数据查询，取满足条件的数据
     * @param object $secondSubQuery
     * @param $bid
     * @param $is_channel
     * @param $is_full_support_after_sale
     */
    public function getThirdSubQuery($secondSubQuery,$bid,$is_channel,$is_full_support_after_sale)
    {
        $getIsNewBbcJavaMode = getIsNewBbcJavaMode();
        $getIsNeedCrm        = getIsNeedCrm();
        $alias_stock_table = Stockinfo::instance()->getTable();
        $query = Stockinfo::instance()
        ->from($alias_stock_table." as outter_stb")
        ->select($this->getGoodsColumns())
        ->joinSub($secondSubQuery,"f_stock",function($join)
        {
            $join->on("f_stock.max_stock_id","=","outter_stb.ID");
        })
        ->leftJoin("stockinfouser_s2b as u_stock",function($join) use($bid)
        {
            $join->on("u_stock.StockID","=","outter_stb.ID")
            ->where("u_stock.BuID",$bid)
            ->where("u_stock.IsDisable",0)
            ->where("u_stock.StockRemainNumber",'>',0);
        })
        ->join("suppliercommodity_s2b as outter_scb","outter_scb.ID","=","outter_stb.SupplierCommodityID")
        ->join("commodityarchives_s2b as outter_com",function($join) use ($is_channel,$is_full_support_after_sale,$getIsNewBbcJavaMode,$getIsNeedCrm)
        {
            $join->on("outter_com.ID","=","outter_stb.CommodityArchivesID");
            
            //如果是自营BBC渠道，必须要满足 spu 存在数据
            if( $getIsNewBbcJavaMode == 1 && $getIsNeedCrm == 1 && ($is_channel == 1 || $is_full_support_after_sale == 1) ) {
                $join->where("outter_com.ThirdPartyCrmLinkStatus",1);
                // ->where("outter_com.SpuID",'>',0)
            }
        });
        
        return $query
        ->orderBy('outter_scb.ID','asc')
        ->get()
        ->toArray();
    }
    
    /**
     * 查询优选满足条件数据不进行分页
     * @param $subQuery
     * @param number $page
     * @param number $limit
     */
    public function getBestGoodsList($bid,$subQuery)
    {
        $alias_stock_table = Stockinfo::instance()->getTable();
        $columns = $this->getNotifyChangeGoodsColumns();
        return Stockinfo::instance()
        ->from($alias_stock_table." as outter_stb")
        ->select($columns)
        ->joinSub($subQuery,"f_stock",function($join){
            $join->on("f_stock.max_stock_id","=","outter_stb.ID");
        })
        ->leftJoin("stockinfouser_s2b as u_stock",function($join) use($bid) {
            $join->on("u_stock.StockID","=","outter_stb.ID")
            ->where("u_stock.BuID",$bid)
            ->where("u_stock.IsDisable",0)
            ->where("u_stock.StockRemainNumber",'>',0);
        })
        ->join("suppliercommodity_s2b as outter_scb","outter_scb.ID","=","outter_stb.SupplierCommodityID")
        ->join("commodityarchives_s2b as outter_com","outter_com.ID","=","outter_stb.CommodityArchivesID")
        ->get()
        ->toArray();
    }
    
    /**
     * 获取第一次分组子查询  min_price
     * @param int $bid
     * @param array $where
     * @param array $receive_data
     * @param int $queryType (1-查询分组总条数，2-查询分组分页，3-查询指定范围分组数据)
     * @param array $extra （扩展字段）
     */
    public function getFirstSubQuery(int $bid,array $where,array $receive_data,int $queryType,array $extra = [])
    {
        //是否是查询分组数据总数
        if( $queryType == 1 )
        {
            $fields = [
                Db::raw("count(DISTINCT stb.SupplierCommodityID) as total"),
            ];
        }
        else if( $queryType == 2 ) //分组分页
        {
            $fields = [
                Db::raw("DISTINCT stb.SupplierCommodityID"),
            ];
        } 
        else if( in_array($queryType,[3,4]) ) //查询指定供应商商品的优选数据，降低聚合求职group by 性能问题
        {
            $fields = [
                "stb.SupplierCommodityID",
                Db::raw("min(stb.BatchSpecMinSinglePrice) AS BatchSpecMinSinglePrice"),                
            ];
        } else {
            return [];
        }
        
        
        //是否是BBC自营渠道
        $is_channel = isset($extra['is_channel']) && $extra['is_channel'] == 1 ? 1 : 0 ;
        $getIsTomoMode = getIsTomoMode();
        $is_full_support_after_sale = isset($extra['is_full_support_after_sale']) && $extra['is_full_support_after_sale'] == 1 ? 1 : 0 ;
        $getIsNewBbcJavaMode = getIsNewBbcJavaMode();
        $getIsNeedCrm = getIsNeedCrm();
        $where = array_merge($where['where'],$where['baseWhere']);
        $alias_stock_table = Stockinfo::instance()->getTable();
        $firstSubQuery = Stockinfo::instance()
        ->from($alias_stock_table." as stb")
        ->select($fields)
        ->join("suppliercommodity_s2b as scb","stb.SupplierCommodityID","=","scb.ID")
        ->join("suppliercompany_s2b as inner_supplier","inner_supplier.ID","=","stb.SupplierCompanyID")
        ->join("warehouseinfo_s2b as inner_wh","inner_wh.ID","=","stb.WarehouseID")
        ->join("commodityarchives_s2b as com",function($join) use ($is_channel,$is_full_support_after_sale,$getIsNewBbcJavaMode,$getIsNeedCrm)
        {
            $join->on("com.ID","=","stb.CommodityArchivesID");
            //如果是自营BBC渠道，必须要满足 spu 存在数据
            if( $getIsNewBbcJavaMode == 1 && $getIsNeedCrm == 1 && ($is_channel == 1 || $is_full_support_after_sale) ) {
                $join->where("com.ThirdPartyCrmLinkStatus",1);
                // ->where("com.SpuID",'>',0)
            }
        });
        
        $firstSubQuery->where("inner_supplier.CompanyStatus",1)
        ->where("inner_supplier.IsBbcCommodity",0)
        ->where("inner_wh.ExamineState",1)
        ->where("com.SelfBuild",0);
        
        //tomo云仓业务模式
        if( $getIsTomoMode == 1 ) {
            $firstSubQuery->where('scb.LinkEventIdStatus',1)->where('scb.IsLinkGoodsRecord',1);
        }
        
        //如果有标签搜索
        if( $receive_data )
        {
            $GoodsTagIDs = [];
            if( $receive_data['GoodsSettingMode'] == self::GOODS_SETTING_MODE_BASE && !empty($receive_data['GoodsBaseSettings']['GoodsTagIDs']) && is_array($receive_data['GoodsBaseSettings']['GoodsTagIDs']) ) {
                $GoodsTagIDs = $receive_data['GoodsBaseSettings']['GoodsTagIDs'];
            } else if( $receive_data['GoodsSettingMode'] == self::GOODS_SETTING_MODE_ADVANCE && !empty($receive_data['GoodsAdvanceSettings']['GoodsTagIDs']) && is_array($receive_data['GoodsAdvanceSettings']['GoodsTagIDs']) ) {
                $GoodsTagIDs = $receive_data['GoodsAdvanceSettings']['GoodsTagIDs'];
            }
        
            if( !empty($GoodsTagIDs) )
            {
                $tagSubQuery = SupplierCommodityTag::instance()->select([
                    Db::raw("DISTINCT SupplierCommodityID")
                ])->whereIn('TagID',$GoodsTagIDs);
                $firstSubQuery->joinSub($tagSubQuery,"scb_tag",function($join)
                {
                    $join->on('scb_tag.SupplierCommodityID', '=', 'stb.SupplierCommodityID');
                });
            }
        }
        
        //指定商品导入
        if( isset($receive_data['GoodsSettingMode'])
            && $receive_data['GoodsSettingMode'] == self::GOODS_SETTING_MODE_ADVANCE
            && isset($receive_data['GoodsAdvanceSettings']['SupplierChoice'])
            && isset($receive_data['GoodsAdvanceSettings']['SupplierChoice']['mode'])
            && $receive_data['GoodsAdvanceSettings']['SupplierChoice']['mode'] == self::SUPPLIER_CHOICE_MODE_WH
            )
        {
            $firstSubQuery->join('commodity_optimization_import as ci',function($join) use ($receive_data) 
            {
                $join->on("ci.SupplierSKUID","=","stb.SupplierCommodityID")->where("ci.BuID",$receive_data['bid']);
            });
            $this->IsImportGoods = true;
        }
        
        $firstSubQuery->whereRaw(implode(" AND ", $where));
        
        //查询总数
        if( $queryType == 1 )
        {
            return $firstSubQuery->first()->toArray();
        } 
        else if( $queryType == 2 )//是否使用分组分页
        {
            $offset = ($extra['page'] - 1) * $extra['limit'];

            $subQuery = $firstSubQuery
            ->offset($offset)
            ->orderBy("stb.SupplierCommodityID","asc")
            ->limit($extra['limit']);

           return Stockinfo::instance()->from($alias_stock_table." as st")->joinSub($subQuery,"stsub",function($join){
                $join->on('st.SupplierCommodityID', '=', 'stsub.SupplierCommodityID');
            })->select('st.SupplierCommodityID');

            
            
        }
        else if( $queryType == 3 )//查询指定供应商商品数据
        {
            return $firstSubQuery
            ->whereIn('scb.ID',$extra['SupplierCommodityIDs'])
            ->groupBy("stb.SupplierCommodityID");
        }
        else if( $queryType == 4 )//查询指定的主档案数据
        {
            return $firstSubQuery
            ->whereIn('com.ID',$extra['SkuIDS'])
            ->groupBy("stb.SupplierCommodityID");
        } else {
            return [];
        }
    }    
    
    /**
     * 获取第二次分组子查询 max_id
     * @param array $firstSubQuery
     * @param int $where
     */
    public function getSecondSubQuery($firstSubQuery,array $where = [])
    {
        $alias_stock_table = Stockinfo::instance()->getTable();
        $c_stock_where = $where['c_stock_where'];
        return Stockinfo::instance()
        ->from($alias_stock_table." as c_stock")
        ->select([
            Db::raw("max(c_stock.ID) AS max_stock_id")
        ])
        ->joinSub($firstSubQuery,"b_stock",function($join) use ( $c_stock_where )
        {
            $join->on('b_stock.SupplierCommodityID', '=', 'c_stock.SupplierCommodityID')
            ->on('b_stock.BatchSpecMinSinglePrice','=','c_stock.BatchSpecMinSinglePrice');
            if( $c_stock_where ) {
                $join->whereRaw($c_stock_where);
            }
        })
        ->join('suppliercompany_s2b as sp','sp.ID','=','c_stock.SupplierCompanyID')
        ->whereRaw(Db::raw("IF ( sp.FastDeliveryType = 1, c_stock.Number + c_stock.NumberLock >= 0, c_stock.Number + c_stock.NumberLock > 0 )"))
        ->groupBy("c_stock.SupplierCommodityID");
    }
    
    /**
     * 检查登录
     * @param array $parameters
     */
    public function checkLogin( $parameters = [] )
    {
        if( empty($parameters['token']) ) {
            return Normal::returnCode(Normal::FAIL,"参数token缺失");
        }
        
        if( empty($parameters['requestData']) ) {
            return Normal::returnCode(Normal::FAIL,"参数requestData缺失");
        }
        
        if( !isset($parameters['requestData']['bid']) ) {
            return Normal::returnCode(Normal::FAIL,"参数requestData.bid缺失");
        }
        
        return ManageWsUserAuthService::instance()->checkUserLoginByToken($parameters['token']);
    }
    
    /**
     * 筛选参数处理
     * @param array $param
     */
    public function getWhereParameters( $param = [] )
    {
        $where      = [];
        $_stb_where = [];
        
        if( !empty($param['SkuIDS']) ) {
            $string = implode(",", $param['SkuIDS']);
            $where[] = " com.ID IN ({$string})";
        }
        
        if( !empty($param['SupplierSKUIDS']) ) {
            $string = implode(",", $param['SupplierSKUIDS']);
            $where[] = " scb.ID IN ({$string})";
        }
        
        if( empty($param['GoodsSettingMode']) || !in_array($param['GoodsSettingMode'],[self::GOODS_SETTING_MODE_BASE,self::GOODS_SETTING_MODE_ADVANCE])) {
            return Normal::returnCode(Normal::FAIL,"【基础配置或高级配置必须任选其一！】");
        }
        
        //如果是基础配置
        if( $param['GoodsSettingMode'] == self::GOODS_SETTING_MODE_BASE ) 
        {
            if( empty($param['GoodsBaseSettings']) ) {
                return Normal::returnCode(Normal::FAIL,"【基础配置参数异常】");
            }
            
            $GoodsSettings = $param['GoodsBaseSettings'];
            if( !empty($GoodsSettings['GoodsTypes']) && is_array($GoodsSettings['GoodsTypes']) ) {
                $goodsTypes = implode(",", $GoodsSettings['GoodsTypes']);
                $where[] = "scb.SupplierCommodityType in({$goodsTypes})";
            }
        }
        
        $where_c_stock = '';
        
        //如果是高级配置
        if( $param['GoodsSettingMode'] == self::GOODS_SETTING_MODE_ADVANCE )
        {
            if( empty($param['GoodsAdvanceSettings']) ) {
                return Normal::returnCode(Normal::FAIL,"【高级配置参数异常】");
            }
            
            $GoodsAdvanceSettings = $param['GoodsAdvanceSettings'];
            
            //指定供应商
            if( empty($GoodsAdvanceSettings['SupplierChoice']) ) {
                return Normal::returnCode(Normal::FAIL,"【高级配置参数SupplierChoice异常】");
            }
            
            //确认选择高级模式
            $SupplierChoice = $GoodsAdvanceSettings['SupplierChoice'];
            if( empty($SupplierChoice['mode'] ) ) {
                return Normal::returnCode(Normal::FAIL,"【高级配置参数SupplierChoice.mode缺失】");
            }
            
            if( !in_array($SupplierChoice['mode'],[self::SUPPLIER_CHOICE_MODE_SP,self::SUPPLIER_CHOICE_MODE_WH]) ) {
                return Normal::returnCode(Normal::FAIL,"【高级配置参数SupplierChoice.mode错误】");
            }

            //指定供应商
            if( $SupplierChoice['mode'] == self::SUPPLIER_CHOICE_MODE_SP ) 
            {
                if( empty($SupplierChoice['SupplierChoiceMode']) ) {
                    return Normal::returnCode(Normal::FAIL,"【高级配置参数SupplierChoice.SupplierChoiceMode缺失】");
                }
                
                if( !in_array($SupplierChoice['SupplierChoiceMode'], ['1','2']) ) {
                    return Normal::returnCode(Normal::FAIL,"【高级配置参数SupplierChoice.SupplierChoiceMode错误】");
                }
          
                //非全部选择
                if( $SupplierChoice['SupplierChoiceMode'] == 1 ) 
                {
                    if( empty($SupplierChoice['SupplierList']) ) {
                        return Normal::returnCode(Normal::FAIL,"【高级配置指定供应商情况下，必须至少选择一个供应商！】");
                    }
                    
                    $supplier_list_where = [];
                    foreach ($SupplierChoice['SupplierList'] as $item )
                    {
                        $supplier_where = [];
                        if( !empty($item['SupplierCompanyID']) ) {
                            $supplier_where[] = "stb.SupplierCompanyID = {$item['SupplierCompanyID']}";
                        }
                        
                        if( !empty($item['GoodsTypes']) && is_array($item['GoodsTypes'])) {
                            $GoodsTypes = implode(",", $item['GoodsTypes']);
                            $supplier_where[] = "scb.SupplierCommodityType in({$GoodsTypes})";
                        }
                        
                        if (empty($item['IsSettlement'])){
                            $item['IsSettlement']=1;
                        }
                        
                        if( empty($item['ClassSetting']) ) {
                            return Normal::returnCode(Normal::FAIL,"【高级配置SupplierList.ClassSetting缺失】");
                        }
                        
                        $ClassSetting = $item['ClassSetting'];
                        if( empty($ClassSetting['GoodsClassChoiceMode']) || !in_array($ClassSetting['GoodsClassChoiceMode'], ['1','2'])) {
                            return Normal::returnCode(Normal::FAIL,"【高级配置SupplierList.GoodsClassChoiceMode不正确】");
                        }
                        
                        //GoodsClassChoiceMode= 1 代表选择指定分类
                        $class_where = [];
                        if( $ClassSetting['GoodsClassChoiceMode'] == 1 && !empty($ClassSetting['GoodsClassChoiceList']) ) 
                        {
                            $GoodsClassChoiceList = $ClassSetting['GoodsClassChoiceList'];
                            foreach ($GoodsClassChoiceList as $item )
                            {
                                //当前供应商下的一级分类
                                if( isset($item['classLevel']) && $item['classLevel'] == 1 && !empty($item['classIDs']) && is_array($item['classIDs']) ) {
                                    $classIDs = implode(",",$item['classIDs']);
                                    $class_where[] = "com.FirstClassificationID in({$classIDs})";
                                }
                                
                                //当前供应商下的二级分类
                                if( isset($item['classLevel']) && $item['classLevel'] == 2 && !empty($item['classIDs']) && is_array($item['classIDs']) ) {
                                    $classIDs = implode(",",$item['classIDs']);
                                    $class_where[] = "com.SecondClassificationID in({$classIDs})";
                                }
                                
                                //当前供应商下的三级分类
                                if( isset($item['classLevel']) && $item['classLevel'] == 3 && !empty($item['classIDs']) && is_array($item['classIDs']) ) {
                                    $classIDs = implode(",",$item['classIDs']);
                                    $class_where[] = "com.ThirdClassificationID in({$classIDs})";
                                }
                            }
                        }
                        
                        //判断是否有分类筛选
                        if( $class_where ) {
                            $supplier_where[] = "(". implode(" OR ", $class_where) ." )";
                        }
                        
                        $supplier_list_where[] = "(". implode(" AND ", $supplier_where)." )";
                    }
                    
                    $where[] = "(". implode(" OR ", $supplier_list_where) ." )";
                }
                
                
                //是否包邮
                if( isset($GoodsAdvanceSettings['IsFreeShipping']) && in_array($GoodsAdvanceSettings['IsFreeShipping'],['0','1']) )
                {
                    $IsFreeShipping = (int)$GoodsAdvanceSettings['IsFreeShipping'];
                    $where[] = "scb.IsFreeShipping = {$IsFreeShipping}";
                }
                
                //指定关区
                if( !empty($GoodsAdvanceSettings['GoodsCustoms']) && is_array($GoodsAdvanceSettings['GoodsCustoms']) )
                {
                    $GoodsCustomIDs = implode(",", $GoodsAdvanceSettings['GoodsCustoms']);
                    $where[] = "scb.CustomID in({$GoodsCustomIDs})";
                }
                
                //统一设置库存、校期
                if( !isset($GoodsAdvanceSettings['AllClassSettingMode']) ) {
                    return Normal::returnCode(Normal::FAIL,"【高级配置-库存效期要求设置参数AllClassSettingMode不能为空】");
                }
                
                //设置分类对应条件
                if( $GoodsAdvanceSettings['AllClassSettingMode'] == 2 ) 
                {
                    if( ! empty($GoodsAdvanceSettings['AllClassSettingList']) ) 
                    {
                        $a_c_where = [];
                        foreach ($GoodsAdvanceSettings['AllClassSettingList'] as $item ) 
                        {
                            $c_where = [];
                            if( !empty($item['classID']) ) 
                            {
                                //有库存范围要求
                                if( !empty($item['GoodsStockSetting']) ) {
                                    $GoodsStockSetting = $item['GoodsStockSetting'];
                                    if( !empty($GoodsStockSetting['mode']) && $GoodsStockSetting['mode'] == 2 &&
                                        !empty($GoodsStockSetting['min']) && !empty($GoodsStockSetting['max']) &&
                                        $GoodsStockSetting['max'] > $GoodsStockSetting['min'] && 
                                        $GoodsStockSetting['min'] > 0
                                        )
                                    {
                                        $c_where[] = "(stb.Number >= {$GoodsStockSetting['min']} AND stb.Number <= {$GoodsStockSetting['max']})";
                                        $this->IsStockNumberLimit = true;
                                    }
                                }
                                
                                //有效期要求
                                if( !empty($item['PeriodSetting']) ) {
                                    $PeriodSetting = $item['PeriodSetting'];
                                    if( !empty($PeriodSetting['mode']) && $PeriodSetting['mode'] == 2 &&
                                        !empty($PeriodSetting['months']) && !empty($PeriodSetting['months']) &&
                                        $PeriodSetting['months'] > 0
                                        )
                                    {
                                        $months = $PeriodSetting['months'];
                                        $current_month = date("Y-m-d 00:00:00"); 
                                        $strtime = strtotime("+ {$months} Month");
                                        $feature_date = date("Y-m-d",$strtime);
                                        $c_where[] = "((stb.CalibrationPeriodTime >= '{$feature_date}' AND stb.IsHasPeriodTime =1) or stb.IsHasPeriodTime = 0 )";
                                        $this->IsGoodsExpireLimit = true;
                                    }
                                }

                                //有商品类型要求
                                if( !empty($item['shopTypeSetting']) ) {
                                    $GoodsTypesSetting = $item['shopTypeSetting'];
                                    if(!empty($GoodsTypesSetting['mode']) && $GoodsTypesSetting['mode'] == 2 &&
                                        !empty($GoodsTypesSetting['shopType'])){
                                        if (count($GoodsTypesSetting['shopType'])==1){
                                            $GoodsType=current($GoodsTypesSetting['shopType']);
                                            $c_where[]="(scb.SupplierCommodityType={$GoodsType})";
                                        } else {
                                            $GoodsType=implode(',',$GoodsTypesSetting['shopType']);
                                            $c_where[]="(scb.SupplierCommodityType in ({$GoodsType}))";
                                        }
                                    }
                                }
                                
                                //二级分类
                                $c_where[] = "com.SecondClassificationID='{$item['classID']}'";
                            }
                            
                            if( $c_where ) {
                                $a_c_where[] = "(". implode(" AND ", $c_where) ." )";
                            }
                        }
                        
                        if( $a_c_where ) {
                            $_sql_where = "(". implode(" OR ", $a_c_where) ." )";
                            //$where_c_stock = str_replace("stb.", "c_stock.", $_sql_where);
                            $where[] = $_sql_where;
                        }
                    }
                } else {
                    
                    //统一设置
                    if( empty($GoodsAdvanceSettings['GlobalClassSetting']) ) {
                        return Normal::returnCode(Normal::FAIL,"【高级配置-库存效期要求设置参数统一设置GlobalClassSetting不能为空】");
                    }
                    
                    $GlobalClassSetting = $GoodsAdvanceSettings['GlobalClassSetting'];
                    $c_where = [];
                    
                    //有库存范围要求
                    if( !empty($GlobalClassSetting['GoodsStockSetting']) ) {
                        $GoodsStockSetting = $GlobalClassSetting['GoodsStockSetting'];
                        if( !empty($GoodsStockSetting['mode']) && $GoodsStockSetting['mode'] == 2 &&
                            !empty($GoodsStockSetting['min']) && !empty($GoodsStockSetting['max']) &&
                            $GoodsStockSetting['max'] > $GoodsStockSetting['min'] && 
                            $GoodsStockSetting['min'] > 0
                            )
                        {
                            $c_where[] = "(stb.Number >= {$GoodsStockSetting['min']} AND stb.Number <= {$GoodsStockSetting['max']})";
                            $this->IsStockNumberLimit = true;
                        }
                    }
                    
                    //有效期要求
                    if( !empty($GlobalClassSetting['PeriodSetting']) ) {
                        $PeriodSetting = $GlobalClassSetting['PeriodSetting'];
                        if( !empty($PeriodSetting['mode']) && $PeriodSetting['mode'] == 2 &&
                            !empty($PeriodSetting['months']) && !empty($PeriodSetting['months']) &&
                            $PeriodSetting['months'] > 0
                            )
                        {
                            $months = $PeriodSetting['months'];
                            $current_month = date("Y-m-d 00:00:00");
                            $strtime = strtotime("+ {$months} Month");
                            $feature_date = date("Y-m-d",$strtime);
                            $_sql_where = "((stb.CalibrationPeriodTime >= '{$feature_date}' AND stb.IsHasPeriodTime =1) or stb.IsHasPeriodTime = 0 )";
                            $c_where[] = $_sql_where;
                            $where_c_stock = str_replace("stb.", "c_stock.", $_sql_where);
                            $this->IsGoodsExpireLimit = true;
                        }
                    }

                    //有商品类型要求
                    if( !empty($GlobalClassSetting['shopTypeSetting']) ) {
                        $GoodsTypesSetting = $GlobalClassSetting['shopTypeSetting'];
                        if(!empty($GoodsTypesSetting['mode']) && $GoodsTypesSetting['mode'] == 2 &&
                            !empty($GoodsTypesSetting['shopType'])){
                            if (count($GoodsTypesSetting['shopType'])==1){
                                $GoodsType=current($GoodsTypesSetting['shopType']);
                                $c_where[]="(scb.SupplierCommodityType={$GoodsType})";
                            } else {
                                $GoodsType=implode(',',$GoodsTypesSetting['shopType']);
                                $c_where[]="(scb.SupplierCommodityType in ({$GoodsType}))";
                            }
                        }
                    }
                    
                    if( $c_where ) {
                        $where[] = "(". implode(" AND ", $c_where) ." )";
                    }
                }
            }
        }
                
        //基础条件（未删除、已上架、有库存、价格大于0、主档案启用）
        $baseWhere = [];
        $baseWhere[] = "scb.IsDeleted = 0";
        $baseWhere[] = "scb.SaleType = 1";
        $baseWhere[] = "scb.UpstreamSaleType = 1";
        
        //获取是否tomo 云仓模式
        $getIsTomoMode = getIsTomoMode();
        if( $getIsTomoMode == 1 ) {
            $baseWhere[] = "scb.LinkEventIdStatus = 1";
            $baseWhere[] = "scb.IsLinkGoodsRecord = 1";
        }
        
        $baseWhere[] = "stb.BatchSpecMinSinglePrice > 0 ";
        $baseWhere[] = "IF ( inner_supplier.FastDeliveryType = 1, (stb.Number + stb.NumberLock) >= 0,(stb.Number + stb.NumberLock) > 0 )";
        $baseWhere[] = "stb.IsHasPrice = 1 ";
        $baseWhere[] = "stb.IsDeleted = 0 ";
        $baseWhere[] = "com.IsDeleted = 0 ";
        $baseWhere[] = "com.IsForbidden = 0 ";
        $baseWhere[] = "com.IsUseAble = 1 ";
        $baseWhere[] = "com.SelfBuild = 0 ";
        return Normal::returnCode(Normal::SUC,"OK",[
            'stb_where' => $_stb_where,
            'where'     => $where,
            'baseWhere' => $baseWhere,
            'c_stock_where' => $where_c_stock
        ]);
    }
}